#include "Frame.h"

#include <cstdio>

#define UNW_LOCAL_ONLY

#include <libunwind.h>

namespace unwind {

void *Frame::getAddress() {
	unw_cursor_t cursor;
	unw_context_t context;
	unw_getcontext(&context);
	unw_init_local(&cursor, &context);
	for (size_t i = 2; i > 0; --i) {
		if (unw_step(&cursor) == 0) {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return NULL;
		}
	}
	unw_word_t sp;
	unw_get_reg(&cursor, UNW_REG_SP, &sp);
	return (void *) sp;
}

void *Frame::getAddress(size_t _frame) {
	unw_cursor_t cursor;
	unw_context_t context;
	unw_getcontext(&context);
	unw_init_local(&cursor, &context);
	for (size_t i = _frame + 2; i > 0; --i) {
		if (unw_step(&cursor) == 0) {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return NULL;
		}
	}
	unw_word_t sp;
	unw_get_reg(&cursor, UNW_REG_SP, &sp);
	return (void *) sp;
}

void *Frame::getPc() {
	unw_cursor_t cursor;
	unw_context_t context;
	unw_getcontext(&context);
	unw_init_local(&cursor, &context);
	if (unw_step(&cursor) == 0) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return NULL;
	}
	unw_word_t ip;
	unw_get_reg(&cursor, UNW_REG_IP, &ip);
	return (void *) ip;
}

void *Frame::getPc(size_t _frame) {
	unw_cursor_t cursor;
	unw_context_t context;
	unw_getcontext(&context);
	unw_init_local(&cursor, &context);
	for (size_t i = 0; i <= _frame; ++i) {
		if (unw_step(&cursor) == 0) {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return NULL;
		}
	}
	unw_word_t ip;
	unw_get_reg(&cursor, UNW_REG_IP, &ip);
	return (void *) ip;
}

Frame::Frame() {
}

Frame::~Frame() {
}

}
